<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
<title>SIDs: Source and Sink Independent Drivers</title>
<meta name="author" content="Gilman Tolle, Philip Levis, and David Gay" />
<style type="text/css">

/*
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2009/02/03 23:07:32 $
:version: $Revision: 1.13 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/
body {
  font-family: Times;
  font-size: 16px;
}

.first {
  margin-top: 0 ! important }

.last {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1 {
  font-family: Arial, sans-serif;
  font-size: 20px;
}

h1.title {
 text-align: center;
 font-size: 32px;
}

h2 {
 font-size: 16px;
 font-family: Arial, sans-serif;
}

h2.subtitle {
  text-align: center }

h3 {
 font-size: 12px;
 font-family: Arial, sans-serif;
}

hr {
  width: 75% }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;
  background-color: #eeeeee;
  border-color: #000000;
  border-width: thin; 
  font-size: 14px
}

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em;
}

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap;
  }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

tt {}

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="sids-source-and-sink-independent-drivers">
<h1 class="title">SIDs: Source and Sink Independent Drivers</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr class="field"><th class="docinfo-name">TEP:</th><td class="field-body">114</td>
</tr>
<tr class="field"><th class="docinfo-name">Group:</th><td class="field-body">Core Working Group</td>
</tr>
<tr class="field"><th class="docinfo-name">Type:</th><td class="field-body">Documentary</td>
</tr>
<tr><th class="docinfo-name">Status:</th>
<td>Final</td></tr>
<tr class="field"><th class="docinfo-name">TinyOS-Version:</th><td class="field-body">2.x</td>
</tr>
<tr><th class="docinfo-name">Author:</th>
<td>Gilman Tolle, Philip Levis, and David Gay</td></tr>
</tbody>
</table>
<div class="note">
<p class="first admonition-title">Note</p>
<p class="last">This memo documents a part of TinyOS for the TinyOS Community, and
requests discussion and suggestions for improvements.  Distribution
of this memo is unlimited. This memo is in full compliance with
TEP 1.</p>
</div>
<div class="section">
<h1><a id="abstract" name="abstract">Abstract</a></h1>
<p>This memo documents a set of hardware- and sensor-independent interfaces
for data sources and sinks in TinyOS 2.x.</p>
</div>
<div class="section">
<h1><a id="introduction" name="introduction">1. Introduction</a></h1>
<p>Sensing is an integral part of any sensor network application. The
diversity of sensors can lead to a wide variety of different software
interfaces to these sensors. However, the burden of connecting a
general sensor data management application to every one of these
different interfaces suggests that sensors also provide a simple,
general-purpose interface for data acquisition. Therefore, TinyOS 2.0
has telescoping sensor abstractions, providing both sensor-independent
and sensor-specific interfaces. This memo documents a set of hardware-
and sensor-independent interfaces for data sources and sinks in TinyOS
2.x.</p>
</div>
<div class="section">
<h1><a id="sensors-in-tinyos-1-x" name="sensors-in-tinyos-1-x">2. Sensors in TinyOS 1.x</a></h1>
<p>Early TinyOS sensors were generally analog. To sample one of these
sensors, an application makes an analog-to-digital conversion using
the MCU ADC.  Because all early sensors required ADC conversions, the
ADC interface has become the de-facto 1.x sensor interface. However,
the ADC interface was originally designed for inexpensive,
interrupt-driven sampling.  All of its commands and events are async
and sensor values are always 16 bits, although only some subset of the
bits may be significant (e.g., a 12-bit value).</p>
<p>Because sensing is an integral part of high-level application logic,
having asynchronous events means that high-level components
must work with atomic sections, even if the sampling rate is very low
(e.g., every five minutes) and so could be easily placed in a
task. Race conditions are problematic and possible in any real time
multi-tasking design. Race conditions are a failure in design, and
especially difficult to detect at low sampling rates.</p>
<p>Additionally, not all sensors require ADC conversions from the MCU.
Many sensors today are digital. To sample these sensors, the MCU sends
a sample command and receives the corresponding data over a bus (e.g.,
SPI, I2C). The latency involved, combined with possible Resource
arbitration <a class="footnote-reference" href="#id2" id="id1" name="id1">[1]</a>, means that these bus operations are often
synchronous code. In the command direction, this can force a task
allocation to convert async to sync; in the event direction, the
application has to deal with async code even though the event is, in
practice, in a task.</p>
<p>Finally, the simplicity of the ADC interface has led many sensor
modules to introduce several new interfaces for calibration and
control, such as <tt class="docutils literal"><span class="pre">Mic</span></tt> and <tt class="docutils literal"><span class="pre">MagSetting</span></tt>. Because ADCs generally do
not have error conditions, the ADC interface has no way to signal that
a sample failed. This turns out to be important for sensors where the
sampling request is split-phase, such as sensors over a bus. In these
cases, it is possible that the driver accepts the request to sample,
but once acquiring the bus discovers something is wrong with the
sensor. This property has led bus-based sensors to also have a
separate <tt class="docutils literal"><span class="pre">ADCError</span></tt> interface; this interface breaks the basic
TinyOS pattern of a tight coupling between split-phase commands and
their completion events, as the command is in ADC but the completion
event is in ADCError.</p>
<p>All of these complications provide the context of the challenge to
write high-level code that is sensor independent. Sensors, when
possible, should follow an approach similar to the HAA[_haa], where
they have sensor- or sensor-class-specific interfaces for high
performance or special case use, but also simple and common interfaces
for basic and portable use. Providing a telescoping sensor abstraction
allows both classes of use.</p>
</div>
<div class="section">
<h1><a id="sensors-in-tinyos-2-x" name="sensors-in-tinyos-2-x">3. Sensors in TinyOS 2.x</a></h1>
<p>TinyOS 2.x contains several nesC interfaces that can be used to
provide sensor-independent interfaces which cover a range of common
use cases. This document describes these interfaces, and explains how
to use these interfaces to write a Source- or Sink-Independent Driver
(SID). A SID is source/sink independent because its interfaces do not
themselves contain information on the sort of sensor or device they
sit on top of.  A SID SHOULD provide one or more of the interfaces
described in this section.</p>
<p>This table summarizes the SID interfaces:</p>
<table border="1" class="docutils">
<colgroup>
<col width="42%" />
<col width="19%" />
<col width="19%" />
<col width="19%" />
</colgroup>
<tbody valign="top">
<tr><td>Name</td>
<td>Phase</td>
<td>Data type</td>
<td>Section</td>
</tr>
<tr><td>Read</td>
<td>Split</td>
<td>Scalar</td>
<td>3.1</td>
</tr>
<tr><td>Get</td>
<td>Single</td>
<td>Scalar</td>
<td>3.2</td>
</tr>
<tr><td>Notify</td>
<td>Trigger</td>
<td>Scalar</td>
<td>3.3</td>
</tr>
<tr><td>ReadStream</td>
<td>Split</td>
<td>Stream</td>
<td>3.4</td>
</tr>
</tbody>
</table>
<div class="section">
<h2><a id="split-phase-small-scalar-i-o" name="split-phase-small-scalar-i-o">3.1 Split-Phase Small Scalar I/O</a></h2>
<p>The first set of interfaces can be used for low-rate scalar I/O:</p>
<pre class="literal-block">
interface Read&lt;val_t&gt; {
  command error_t read();
  event void readDone( error_t result, val_t val );
}
</pre>
<p>If the <tt class="docutils literal"><span class="pre">result</span></tt> parameter of the <tt class="docutils literal"><span class="pre">Read.readDone</span></tt> and
<tt class="docutils literal"><span class="pre">ReadWrite.readDone</span></tt> events is not SUCCESS, then the memory of the
<tt class="docutils literal"><span class="pre">val</span></tt> parameter MUST be filled with zeroes.</p>
<p>If the call to <tt class="docutils literal"><span class="pre">read</span></tt> has returned SUCCESS, but the <tt class="docutils literal"><span class="pre">readDone</span></tt>
event has not yet been signaled, then a subsequent call to <tt class="docutils literal"><span class="pre">read</span></tt>
MUST return EBUSY or FAIL.  This simple locking technique, as opposed
to a more complex system in which multiple read/readDone pairs may be
outstanding, is intended to reduce the complexity of SID client code.</p>
<p>Examples of sensors that would be suited to this class of interface
include many basic sensors, such as photo, temp, voltage, and ADC
readings.</p>
</div>
<div class="section">
<h2><a id="single-phase-scalar-i-o" name="single-phase-scalar-i-o">3.2 Single-Phase Scalar I/O</a></h2>
<p>Some devices may have their state cached or readily available. In
these cases, the device can provide a single-phase instead of
split-phase operation.  Examples include a node's MAC address (which
the radio stack caches in memory), profiling information (e.g.,
packets received), or a GPIO pin. These devices MAY use the
Get interface:</p>
<pre class="literal-block">
interface Get&lt;val_t&gt; {
  command val_t get();
}
</pre>
</div>
<div class="section">
<h2><a id="notification-based-scalar-i-o" name="notification-based-scalar-i-o">3.3 Notification-Based Scalar I/O</a></h2>
<p>Some sensor devices represent triggers, rather than request-driven
data acquisition. Examples of such sensors include switches,
passive-IR (PIR) motion sensors, tone detectors, and smoke
detectors. This class of event-driven sensors can be presented with
the Notify interface:</p>
<pre class="literal-block">
interface Notify&lt;val_t&gt; {
  command error_t enable();
  command error_t disable();
  event void notify( val_t val );
}
</pre>
<p>The Notify interface is intended for relatively low-rate events (e.g.,
that can easily tolerate task latencies). High-rate events may require
more platform- or hardware-specific async interfaces.</p>
<p>The enable() and disable() command enable and disable notification
events for the interface instance used by a single particular
client. They are distinct from the sensor's power state. For example,
if an enabled sensor is powered down, then when powered up it will
remain enabled.</p>
<p>If <tt class="docutils literal"><span class="pre">enable</span></tt> returns SUCCESS, the interface MUST subsequently
signal notifications when appropriate. If <tt class="docutils literal"><span class="pre">disable</span></tt> returns SUCCESS,
the interface MUST NOT signal any notifications.</p>
<p>The val parameter is used as defined in the Read interface.</p>
</div>
<div class="section">
<h2><a id="split-phase-streaming-i-o" name="split-phase-streaming-i-o">3.4 Split-Phase Streaming I/O</a></h2>
<p>Some sensors can provide a continuous stream of readings, and some
actuators can accept a continuous stream of new data. Depending on the
rate needed and jitter bounds that higher level components can
tolerate, it can be useful to be able to read or write readings in
blocks instead of singly.  For example, a microphone or accelerometer
may provide data at a high rate that cannot be processed quickly
enough when each new reading must be transferred from asynchronous to
synchronous context through the task queue.</p>
<p>The ReadStream interface MAY be provided by a device that can
provide a continuous stream of readings:</p>
<pre class="literal-block">
interface ReadStream&lt;val_t&gt; {

  command error_t postBuffer( val_t* buf, uint16_t count );

  command error_t read( uint32_t usPeriod );

  event void bufferDone( error_t result,
                         val_t* buf, uint16_t count );

  event void readDone( error_t result );
}
</pre>
<p>The postBuffer command takes an array parameterized by the sample
type, and the number of entries in that buffer. A driver can then
enqueue the buffer for filling. The client can call postBuffer() more
than once, to &quot;pre-fill&quot; the queue with any number of buffers. The
size of the memory region pointed to by the buf parameter MUST be at
least as large as the size of a pointer on the node architecture plus
the size of the uint16_t count argument. This requirement supports
drivers that may store the queue of buffers and count sizes by
building a linked list.</p>
<p>After posting at least one buffer, the client can call read() with a
specified sample period in terms of microseconds. The driver then
begins to fill the buffers in the queue, signaling the bufferDone()
event when a buffer has been filled. The client MAY call postBuffer()
after read() in order to provide the device with new storage for
future reads.</p>
<p>If the device ever takes a sample that it cannot store (e.g., due to
buffer underrun), it MUST signal readDone() with an appropriate
failure code. If an error occurs during a read, then the device MUST
signal readDone() with an appropriate failure code. Before a device
signals readDone(), it MUST signal bufferDone() for all outstanding
buffers. If a readDone() is pending, calls to postBuffer MUST return
FAIL.</p>
<p>In the ReadStream interface, <tt class="docutils literal"><span class="pre">postBuffer</span></tt> returns SUCCESS if the buffer
was successfully added to the queue, FAIL otherwise. A return value
of SUCCESS from <tt class="docutils literal"><span class="pre">read</span></tt> indicates reading has begun and the interface
will signal <tt class="docutils literal"><span class="pre">bufferDone</span></tt> and/or <tt class="docutils literal"><span class="pre">readDone</span></tt> in the future. A
return value of FAIL means the read did not begin and the interface
MUST NOT signal <tt class="docutils literal"><span class="pre">readDone</span></tt> or <tt class="docutils literal"><span class="pre">bufferDone</span></tt>. Calls to <tt class="docutils literal"><span class="pre">read</span></tt>
MAY return EBUSY if the component cannot service the request.</p>
</div>
</div>
<div class="section">
<h1><a id="implementation" name="implementation">4. Implementation</a></h1>
<p>An implementation of the Read interface can be found in
<tt class="docutils literal"><span class="pre">tos/system/SineSensorC.nc</span></tt> and <tt class="docutils literal"><span class="pre">tos/system/ArbitratedReadC.nc</span></tt>.</p>
<p>An implementation of the Get interface can be found in
<tt class="docutils literal"><span class="pre">tos/platforms/telosb/UserButtonC.nc</span></tt>.</p>
<p>An implementation of the ReadStream interface can be found in
<tt class="docutils literal"><span class="pre">tos/sensorboards/mts300/MageXStreamC.nc</span></tt>.</p>
<p>Implementations of the Notify interface can be found in
<tt class="docutils literal"><span class="pre">tos/platforms/telosb/SwitchToggleC.nc</span></tt> and
<tt class="docutils literal"><span class="pre">tos/platforms/telosb/UserButtonP.nc</span></tt>.</p>
</div>
<div class="section">
<h1><a id="summary" name="summary">5. Summary</a></h1>
<p>According to the design principles described in the HAA[_haa], authors
should write device drivers that provide rich, device-specific
interfaces that expose the full capabilities of each device. In
addition, authors can use the interfaces described in this memo to
provide a higher-level device-independent abstractions: SIDs. By
providing such an abstraction, driver authors can support developers
who only need simple interfaces, and can reduce the effort needed to
connect a sensor into a more general system.</p>
</div>
<div class="section">
<h1><a id="author-s-address" name="author-s-address">6. Author's Address</a></h1>
<div class="line-block">
<div class="line">Gilman Tolle</div>
<div class="line">501 2nd St. Ste 410</div>
<div class="line">Arch Rock Corporation</div>
<div class="line">San Francisco, CA 94107</div>
<div class="line"><br /></div>
<div class="line">phone - +1 415 692 0828</div>
<div class="line">email - <a class="reference" href="mailto:gtolle&#64;archrock.com">gtolle&#64;archrock.com</a></div>
<div class="line"><br /></div>
<div class="line"><br /></div>
<div class="line">Philip Levis</div>
<div class="line">358 Gates</div>
<div class="line">Computer Science Laboratory</div>
<div class="line">Stanford University</div>
<div class="line">Stanford, CA 94305</div>
<div class="line"><br /></div>
<div class="line">phone - +1 650 725 9046</div>
<div class="line">email - <a class="reference" href="mailto:pal&#64;cs.stanford.edu">pal&#64;cs.stanford.edu</a></div>
<div class="line"><br /></div>
<div class="line"><br /></div>
<div class="line">David Gay</div>
<div class="line">2150 Shattuck Ave, Suite 1300</div>
<div class="line">Intel Research</div>
<div class="line">Berkeley, CA 94704</div>
<div class="line"><br /></div>
<div class="line">phone - +1 510 495 3055</div>
<div class="line">email - <a class="reference" href="mailto:david.e.gay&#64;intel.com">david.e.gay&#64;intel.com</a></div>
<div class="line"><br /></div>
</div>
</div>
<div class="section">
<h1><a id="citations" name="citations">7. Citations</a></h1>
<table class="docutils footnote" frame="void" id="id2" rules="none">
<colgroup><col class="label" /><col /></colgroup>
<tbody valign="top">
<tr><td class="label"><a class="fn-backref" href="#id1" name="id2">[1]</a></td><td>TEP 108: Resource Arbitration.</td></tr>
</tbody>
</table>
</div>
</div>
</body>
</html>
